import React, { useRef, useEffect, useContext, useCallback } from "react";
import { useDidShow } from "@tarojs/taro";
import { TopContext } from "./useTopView";

import { overlayOptionsProps } from '../../types/uses/useOverlay'

const useOverlay = (componentName?: string /** 便于调试LOG */) => {
  const { popup, close, forcedClose, topView } = useContext(TopContext);
  const isShowRef = useRef(false);

  const needShow = useRef(false);
  const componentRef = useRef<React.FC>();
  const optionsRef = useRef<overlayOptionsProps>();
  const resolveRef = useRef<(value: unknown) => void>();
  const rejectRef = useRef<(reason?: any) => void>();

  const componentIdRef = useRef(0); // 当前show出组件唯一标识

  useDidShow(() => {
    isShowRef.current = true;
    if (needShow.current) {
      needShow.current = false;
      if (componentRef.current) {
        _show(componentRef.current, optionsRef.current)
          .then(res => {
            resolveRef.current && resolveRef.current(res);
          })
          .catch(e => {
            rejectRef.current && rejectRef.current(e);
          });
      }
    }
  });

  useEffect(() => {
    return () => {
      componentIdRef.current && close(componentIdRef.current);
    };
  }, [componentIdRef, componentName]);

  const _show = useCallback(
    (component: React.FC, options: overlayOptionsProps = {}) => {
      const id = new Date().getTime();
      componentIdRef.current = id;
      return popup({ id, component }, options);
    },
    [componentIdRef, componentName, popup]
  );

  // needVerifyShow: 是否需要验证组件是否didshow。应当在所有组didshow才能show，但出于部分场景[authbutton]组件显示了，但未走usedidshow，前期先不加判断，只在指定场景加，后期再解决未何部分场景组件显示了却未走usedidshow
  const show = useCallback(
    (
      component: React.FC,
      options: overlayOptionsProps = {},
      needVerifyShow: boolean = false
    ) => {
      // 当前组件未显示，则等待下次显示时主动显示
      if (needVerifyShow && !isShowRef.current) {
        needShow.current = true;
        componentRef.current = component;
        optionsRef.current = options;
        return new Promise((resolve, reject) => {
          resolveRef.current = resolve;
          rejectRef.current = reject;
        });
      }
      return _show(component, options);
    },
    [_show]
  );

  const _close = useCallback(() => {
    componentIdRef.current && close(componentIdRef.current);
  }, [componentIdRef, componentName, close]);

  return { show, close: _close, forcedClose, overlayView: topView };
};

export default useOverlay;
